#include "mpx_supt.h"
#include "R2.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void block_PCB(int argc, char **argv);
void unblock_PCB(int argc, char **argv);
void suspend_PCB(int argc, char **argv);
void resume_PCB(int argc, char **argv);
pcb *allocate_PCB(NULL);
void create_PCB(NULL);
void delete_PCB(NULL);
void free_PCB(pcb *ptr);
void insert_PCB(NULL);
void remove_PCB(NULL);
void setup_PCB(NULL);

pq ready, blocked, suspended, suspended_blocked;

typedef struct
{
    unsigned char *stack_top;
    unsigned char *stack_base;
} stack_area;

void block_PCB(int argc, char **argv ){
char pcb_Name[32]
int name_size = 32;

printf("Enter the process name to block\n");
printf("> ");
sys_req(READ, TERMINAL, pcb_Name, &name_size);

pcb *myPCB = find_PCB(pcb_Name);

if(myPCB == null)
{
	printf("Process \"%s\" not found.", pcb_Name);
}
else
{
	remove_PCB(myPCB);
	insert_PCB(blocked, myPCB);
	printf("Process \"%S\" was successfully blocked", pcb_Name);
}
argc = argc;
argv = argv;
}

void unblock_PCB(int argc, char **argv){

char pcb_Name[32]
int name_size = 32;

printf("Enter the process name to unblock\n");
printf("> ");
sys_req(READ, TERMINAL, pcb_Name, &name_size);

pcb *myPCB = find_PCB(pcb_Name);

if(myPCB == null)
{
	printf("Process \"%s\" not found.", pcb_Name);
}
else
{
	remove_PCB(myPCB);
	insert_PCB(ready, myPCB);
	printf("Process \"%S\" was successfully moved to the ready queue.", pcb_Name);
}
argc = argc;
argv = argv;
}

void suspend_PCB(int argc, char **argv){

char pcb_Name[32]
int name_size = 32;

printf("Enter the process name to suspend\n");
printf("> ");
sys_req(READ, TERMINAL, pcb_Name, &name_size);

pcb *myPCB = find_PCB(pcb_Name);

if(myPCB == null)
{
	printf("Process \"%s\" not found.", pcb_Name);
}
else
{
	remove_PCB(myPCB);
	insert_PCB(suspended, myPCB);
	printf("Process \"%S\" was successfully moved to the suspended queue.", pcb_Name);
}
argc = argc;
argv = argv;
}

void resume_PCB(int argc, char **argv){

char pcb_Name[32]
int name_size = 32;

printf("Enter the process name to resume\n");
printf("> ");
sys_req(READ, TERMINAL, pcb_Name, &name_size);

pcb *myPCB = find_PCB(pcb_Name);

if(myPCB == null)
{
	printf("Process \"%s\" not found.", pcb_Name);
}
else
{
	remove_PCB(myPCB);
	insert_PCB(ready, myPCB);
	printf("Process \"%S\" was successfully moved to the ready queue.", pcb_Name);
}
 argc = argc;
 argv = argv;
}

pcb *allocate_PCB(NULL);
{
	int size = sizeof(pcb)
	int *address;
	pcb *pcb_ptr;
	
	pcb_ptr = sys_alloc_mem(size);
	adress = sys_alloc_mem(1024);
	pcb_ptr->stack_base = address;
	pcb_ptr->stack_top = pcb_ptr->stack_base + size;
	return(&pcb_ptr);
}

void create_PCB(NULL)
{
	char name_Process[32];
	int process_size = 32;
	char pcb_class[32];
	int class_size = 32;
	char pcb_priority[32];
	int priority_size = 32;
	int pcb_prior;
	printf("Enter the name of the process\n");
	sys_req(READ, TERMINAL, name_Process, &process_size);
	printf("Enter the PCB class\n");
	sys_req(READ, TERMINAL, pcb_class, &class_size);
	printf("Enter the priority of the PCB\n");
	sys_req(READ, TERMINAL, pcb_priority, &priority_size);
	pcb_prior = atoi(pcb_priority);
	setup_PCB(name_Process, pcb_class, pcb_priority);
}

void delete_PCB(NULL)
{
	char name_PCB[32];
	int name_size = 32;
	printf("Enter the name of the PCB to be deleted\n");
	sys_req(READ, TERMINAL, name_PCB, &name_size);
	free_PCB(name_PCB);
}

void free_PCB(pcb *ptr)
{
	sys_free_mem(ptr->stack_base);
	sys_free_mem(ptr);
}


void find_pcb(char pname) {

	pqn *temp;

	// search ready
	
	temp = ready.root;
	
	if (!pq_is_empty(ready))
	
		do {
		
			if (strcmp(temp->data->name, pname) == 0) return temp;
			
	} while (temp != NULL);
	
	// search blocked
	
	if (!pq_is_empty(blocked))
	
		do {
		
			if (strcmp(temp->data->name, pname) == 0) return temp;
			
	} while (temp != NULL);
		
	return NULL;

}

void set_priority(int argc, char **arv) {

	pcb *temp;
	int priority = atoi(argv[1]);

	if (argc != 2) printf("Invalid number of arguments. Usage: set_priority process_name priority.\n");

	temp = find_pcb(argv[0]);
	
	if (temp == NULL) {
	
		printf("Process does not exist.");
		return;
		
	}
	
	if (priority < -127 || priority > 128) {
	
		printf("Priority should be in the range -127 to 128\n");
		return;
	
	}
	
	temp->priority = priority;	
	remove_pcb(temp);
	if (temp->state == READY)
	insert_pcb(READY, temp);
	if (temp->state == BLOCKED)
	insert_pcb(BLOCKED, temp);
	
}

void show_pcb (int argc, char **argv) {

	if (argc != 1) printf("Invalid number of arguments. Usage: show_pcb process_name.\n");
	pcb *n = find_pcb(arg[0]);
	printf("Name: %s, Class: %d, Size: %d, Priority: %d, State: %d\n", n->name, n->class, n->memory_size, n->priority, n->state);

}

void show_all(int argc, char **argv) {

	show_ready();
	show_blocked();

}

void show_ready(int argc, char **argv) {

	pqn *temp;

	if (!pq_is_empty(ready)) {

		printf("Displaying processes in ready queue:\n\n");

		temp = ready.root;

		do {

			printf("Name: %s, Class: %d, Size: %d, Priority: %d, State: %d\n", n->data->name, n->data->class, n->data->memory_size, n->data->priority, n->data->state);
			temp = temp.right;

		} while (temp != NULL);	

	} else printf("No processes in ready queue.");

}

void show_ready(int argc, char **argv) {

	pqn *temp;

	if (!pq_is_empty(ready)) {

		printf("Displaying processes in ready queue:\n\n");

		temp = ready.root;

		do {

			printf("Name: %s, Class: %d, Size: %d, Priority: %d, State: %d\n", n->data->name, n->data->class, n->data->memory_size, n->data->priority, n->data->state);
			temp = temp.right;

		} while (temp != NULL);	

	} else printf("No processes in ready queue.");

}

void show_blocked() {

        pqn *temp;

        if (!pq_is_empty(blocked)) {

                printf("Displaying processes in blocked queue:");

                temp = blocked.root;

                do {

                        printf("Name: %s, Class: %d, Size: %d, Priority: %d, State: %d\n", n->data->name, n->data->class, n->data->memory_size, n->data->priority, n->data->state);
                        temp = temp.right;

                } while (temp != NULL);

        } else printf("No processes in blocked queue.");

}

void insert_PCB(){

}

void remove_PCB(){

}

void setup_PCB(){

}